package com.handong.handserialprogram.thread;

import android.content.Context;
import android.os.Handler;
import android.os.Process;
import android.text.TextUtils;

import com.handong.handserialprogram.R;
import com.handong.handserialprogram.model.entities.MapPersonEntity;
import com.handong.handserialprogram.model.status.MissionOverResponse;
import com.handong.handserialprogram.module.serialport.SerialPortUtil;
import com.handong.handserialprogram.utils.AsyncHttpUtil;
import com.handong.handserialprogram.utils.EventBusUtil;
import com.handong.handserialprogram.utils.JLog;
import com.handong.handserialprogram.utils.MinaUtil;
import com.handong.handserialprogram.utils.SPUtil;
import com.handong.handserialprogram.voice.VoiceImpl;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

import java.net.InetSocketAddress;
import java.util.Date;

import cn.pda.serialport.Tools;

/**
 * Created by userKey on 2017/3/30.
 */

public class UploadRunnable implements Runnable {

    private static final String TAG = UploadRunnable.class.getSimpleName();
    public static final String MISSION_OVER = "mission_over";
    private static final int REMIND_DELAYED_TIME = 55000;

    private SerialPortUtil mSerialPortUtil;
    private NioSocketConnector mConnector;
    private IoSession mSession;

    private boolean mIsConnectedSuccess = false;
    private boolean mIsWork = true;
    private boolean mIsPostMsg = false;

    private Handler mConnectHandler;

    private byte[] mUploadByteArray;
    private Object mLock;
    private Context mContext;
    private boolean isPause=false;

    private Runnable mConnectRemind = new Runnable() {
        @Override
        public void run() {
            VoiceImpl impl = VoiceImpl.getInstance(mContext);
            impl.playHighPriority(R.raw.warning_phone_network_weak);
            mIsPostMsg = false;
            JLog.d(TAG, "mConnectRemind play success.");
        }
    };

    public UploadRunnable(SerialPortUtil serialPortUtil, Object lock, Handler handler, Context context) {
        this.mLock = lock;
        this.mSerialPortUtil = serialPortUtil;
        mContext = context;
        mConnectHandler = handler;
    }

    @Override
    public void run() {
        //设置为后台线程 避免与main线程争夺资源。
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        JLog.d(TAG, "mUploadRunnable is running.");
        while (mIsWork) {

//            if (!isPause)
//            {
                initConnection();//初始化连接

                uploadDeviceInformation();//根据不同情况上传信息。

                dealLongTimeConnectFail();

                try {
                    //休眠等待其他线程唤醒。
                    synchronized (mLock) {
                        mLock.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (!mIsWork) {
                    break;
                }
//            }
//            else{
//                try {
//                    //休眠等待其他线程唤醒。
//                    synchronized (mLock) {
//                        mLock.wait();
//                    }
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                if (!mIsWork) {
//                    isPause=false;
//                    break;
//                }
//            }

        }
        releaseRes();
        JLog.d(TAG, "The upload thread " + Thread.currentThread().getId() + " is stopped.");
    }

    /**
     * 暂停上传
     */
    private void pauseUpload()
    {
        isPause=true;
    }

    /**
     * 恢复上传
     */
    private void resumeUpload()
    {
        isPause=false;
        synchronized (mLock){
            mLock.notifyAll();
        }
    }

    public void setUploadByteArray(byte[] uploadByteArray) {
        mUploadByteArray = uploadByteArray;
    }

    /**
     * 上传数据信息
     */
    private void uploadDeviceInformation() {

        try {
            if (mSession != null && mSession.isConnected()) {
                if (mIsPostMsg) {
                    connectResume();
                }
                if (!mIsConnectedSuccess) {
                    Thread.sleep(1500);//首次连接成功，等待服务端认证。
                    mIsConnectedSuccess = true;
                }
                if (mUploadByteArray != null) {
                    byte[] buff = mUploadByteArray;
                    String data = Tools.byteToHexString(buff);
                    JLog.d(TAG, "Upload Data:"+data);
                    IoBuffer buffer = IoBuffer.wrap(buff);
                    mSession.write(buffer);

                    JLog.d(TAG, "socket upload success.");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            JLog.d(TAG, "socked append exception.");
            mSession = null;
        }
    }

    /**
     * 初始化Mina。
     */
    private void initConnection() {
        if (!AsyncHttpUtil.isNetworkConnected(mContext, false)) {
            return;
        }
        if (mConnector == null) {
            mConnector = new NioSocketConnector();
            mConnector.setConnectTimeoutMillis(10000);
            mConnector.getSessionConfig().setReceiveBufferSize(1024 * 1024);
            mConnector.getSessionConfig().setSendBufferSize(1024 * 1024);
            mConnector.getSessionConfig().setKeepAlive(true);//保持长链接。
            //mConnector.getFilterChain().addLast(
            //       "codec",
            //       new ProtocolCodecFilter(new TextLineCodecFactory(Charset
            //               .forName("UTF-8"),
            //               LineDelimiter.WINDOWS.getValue(),
            //               LineDelimiter.WINDOWS.getValue())));
            mConnector.setHandler(new MinaClientHandler() {//处理任务结束。

                @Override
                public void messageReceived(IoSession session, Object message) throws Exception {
                    dealServerResponse(message);//接收的数据
                }
            });

            //动态配置IP。
            String ip = SPUtil.getStringValue(SPUtil.SERVER_IP);
            int port = SPUtil.getIntValue(SPUtil.UPLOAD_PORT);
            //String ip = "10.1.200.95";
            //int port = 9503;
            mConnector.setDefaultRemoteAddress(new InetSocketAddress(ip, port));

            mConnector.addListener(new IoListener() {

                @Override
                public void sessionDestroyed(IoSession arg0) throws Exception {
                    super.sessionDestroyed(arg0);
                    mSession = null;
                    mIsConnectedSuccess = false;
                    dealLongTimeConnectFail();//连接失败
                }
            });
        }

        if (mSession == null) {
            try {
                ConnectFuture future = mConnector.connect();
                future.awaitUninterruptibly();// 等待连接创建完成
                mSession = future.getSession();
            } catch (Exception e) {
                JLog.d(TAG, "连接服务端失败");
                e.printStackTrace();
                mSession = null;
            }
        }
    }

    private boolean isReceiveUpdateRoute=false;
    private int plannRouteCount=0;
    private String plannRouteStr="";
    private Long receiveTimeInt=System.currentTimeMillis();
    /**
     * 处理服务器返回结果
     */
    private void dealServerResponse(Object message) {
        IoBuffer ioBuffer = (IoBuffer) message;
        String order = MinaUtil.ioBufferToString(ioBuffer);
        JLog.d(TAG, "i客户端接收到的信息为:" + order);
        if (TextUtils.isEmpty(order)) {
            return;
        }
        if (isReceiveUpdateRoute&&(System.currentTimeMillis()-receiveTimeInt)<100)
        {
            //100ms以内获取到的数据且收到数据后认为一包未收完
            plannRouteStr+=order;
            if (plannRouteStr.length()>=plannRouteCount)
            {
                EventBusUtil.post(new MissionOverResponse(MissionOverResponse.UPDATE_ROUTE, plannRouteStr));
                isReceiveUpdateRoute=false;
                plannRouteStr="";
                plannRouteCount=0;
            }
        }
        else{
            isReceiveUpdateRoute=false;
            plannRouteStr="";
            plannRouteCount=0;
            String[] childArr = order.split("&");
            if (childArr.length < 3) {
                return;
            }
            String code = SPUtil.getStringValue(SPUtil.LOGIN_CODE);
            if (!childArr[0].equals(code)) {
                return;
            }
            if (!childArr[1].equals(SPUtil.getStringValue(SPUtil.MISSION_ID))) {
                return;
            }
            if ("1".equals(childArr[2])) {
                EventBusUtil.post(new MissionOverResponse(MissionOverResponse.OVER_SUCCESS));// 服务器结束任务成功
            } else if ("2".equals(childArr[2])) {
                EventBusUtil.post(new MissionOverResponse(MissionOverResponse.OVER_REJECT));// 服务器不允许结束任务
            } else if ("3".equals(childArr[2])) {
                EventBusUtil.post(new MissionOverResponse(MissionOverResponse.SERVER_REQUEST));// 服务器请求结束任务
            } else if ("4".equals(childArr[2])) {
                mSerialPortUtil.remindRingGPSLost();
            } else if ("101".equals(childArr[2])) {
                if (mSerialPortUtil != null) {
                    mSerialPortUtil.noiseFootRing(childArr[3]);//脚环报警
                }
            } else if ("102".equals(childArr[2])) {//更新犯人位置
                MapPersonEntity entity = new MapPersonEntity(childArr[3]);
                entity.setLat(Double.parseDouble(childArr[5]));
                entity.setLng(Double.parseDouble(childArr[4]));
                EventBusUtil.post(entity);
            } else if ("103".equals(childArr[2])) {//_&230&103&88CE
                if (mSerialPortUtil != null) {
                    mSerialPortUtil.closeFootRingAlarmFromServer(childArr[3]);//来自服务器的关闭警报命令。
                }
            }else if ("104".equals(childArr[2])) {//_&230&103&88CE
                if (mSerialPortUtil != null) {
                    mSerialPortUtil.openFootRingAlarmFromServer(childArr[3]);//来自服务器的开启警报命令。
                }
            }else if ("105".equals(childArr[2])) {//_&230&103&88CE
                if(childArr[3].equals("1"))
                {
                    //发送围栏越界报警
                    if (mSerialPortUtil != null) {
                        mSerialPortUtil.addSound(R.raw.warnning_phone_fence_out);
                    } 
                }
                else if(childArr[3].equals("2"))
                {
                    //发送围栏返回正常提示
                    if (mSerialPortUtil != null) {
                        mSerialPortUtil.addSound(R.raw.info_phone_fence_normal);
                    }
                }
            }
            else if("106".equals(childArr[2])){//任务恢复
                EventBusUtil.post(new MissionOverResponse(MissionOverResponse.SERVER_RESUME_MISSION));//任务恢复
            }
            else if("111".equals(childArr[2]))
            {
                int count= Integer.parseInt(childArr[3]);
                if (count==childArr[4].length()) {
                    EventBusUtil.post(new MissionOverResponse(MissionOverResponse.UPDATE_ROUTE, childArr[4]));
                }
                else{
                    plannRouteCount=count;
                    isReceiveUpdateRoute=true;
                    plannRouteStr=childArr[4];
                    receiveTimeInt=System.currentTimeMillis();
                }
            }
        }

    }

    /**
     * 连接失败
     */
    protected void dealLongTimeConnectFail() {
        if (mIsPostMsg || !mIsWork) {
            return;
        }
        if (mSession == null && !mIsConnectedSuccess) {
            JLog.d(TAG, "mConnectRemind has been posted.");
            mIsPostMsg = true;
            mConnectHandler.postDelayed(mConnectRemind, REMIND_DELAYED_TIME);
        }
    }

    protected void connectResume() {
        mConnectHandler.removeCallbacks(mConnectRemind);
        mIsPostMsg = false;
        JLog.d(TAG, "mConnectRemind has been removed.");
    }

    public void releaseRes() {
        closeMinaSocket();
    }

    public void closeMinaSocket() {
        mConnectHandler = null;
        mContext = null;
        if (mSession != null) {
            mSession.closeNow();
            //mSession.getCloseFuture().awaitUninterruptibly(1000);
            mSession = null;
        }
        if (mConnector != null) {
            mConnector.dispose();
            mConnector = null;
        }
        mSerialPortUtil = null;
    }

    public void destroy() {
        this.mIsWork = false;
        if (mIsPostMsg) connectResume();
        mConnectHandler = null;
        mConnectRemind = null;
        synchronized (this.mLock) {
            this.mLock.notify();
        }
    }
}
